﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Order.MicroService.Domain;
using Order.MicroService.IRepository;
using Order.MicroService.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Order.MicroService.Repository
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new()
    {
        //子类继承父类的时候可以直接使用MyDbContext
        protected readonly MyDbContext db;

        #region 查询
        public BaseRepository(MyDbContext myDbContext)
        {
            db = myDbContext;
        }

        public TEntity GetEntity(Expression<Func<TEntity, bool>> where)
        {
            return db.Set<TEntity>().AsNoTracking().Where(where).FirstOrDefault();
        }

        public async Task<TEntity> GetEntityAsync(Expression<Func<TEntity, bool>> where)
        {
            return await db.Set<TEntity>().AsNoTracking().Where(where).FirstOrDefaultAsync();
        }

        public TEntity GetEntityById(int Id)
        {
            var entity = db.Set<TEntity>().Find(Id);
            if (entity != null)
            {
                //设置不跟踪上下文实体
                db.Entry(entity).State = EntityState.Detached;
            }
            return entity;
        }

        public async Task<TEntity> GetEntityByIdAsync(int Id)
        {
            var model = await db.Set<TEntity>().FindAsync(Id);
            if (model != null)
            {
                db.Entry(model).State = EntityState.Detached;
            }
            return model;
        }

        public IEnumerable<TEntity> GetList(Expression<Func<TEntity, bool>> where)
        {
            return db.Set<TEntity>().AsNoTracking().Where(where).ToList();
        }

        public async Task<IEnumerable<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> where)
        {
            return await db.Set<TEntity>().AsNoTracking().Where(where).ToListAsync();
        }

        public Pagination<TEntity> GetPageList(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> where)
        {
            int count = db.Set<TEntity>().AsNoTracking().Where(where).Count();
            var list = db.Set<TEntity>().AsNoTracking().Where(where).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            int totalPages = (count + pageSize - 1) / pageSize;
            return new Pagination<TEntity>() { PageIndex = pageIndex, PageSize = pageSize, TotalCount = count, TotalPages = totalPages, Data = list };
        }

        public async Task<Pagination<TEntity>> GetPageListAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> where)
        {
            int count = await db.Set<TEntity>().AsNoTracking().Where(where).CountAsync();
            var list = await db.Set<TEntity>().AsNoTracking().Where(where).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
            int totalPages = (count + pageSize - 1) / pageSize;
            return new Pagination<TEntity>() { PageIndex = pageIndex, PageSize = pageSize, TotalCount = count, TotalPages = totalPages, Data = list };
        }
        #endregion

        #region 修改
        public int Update(TEntity entity)
        {
            try
            {
                db.Entry(entity).State = EntityState.Modified;
                return db.SaveChanges();
            }
            catch (Exception)
            {
                return 0;
            }
        }

        public async Task<int> UpdateAsync(TEntity entity)
        {
            try
            {
                db.Entry(entity).State = EntityState.Modified;
                return await db.SaveChangesAsync();
            }
            catch (Exception)
            {
                return 0;
            }
        }
        #endregion

        #region 删除
        public int Delete(TEntity entity)
        {
            db.Attach(entity);
            db.Remove(entity);
            return db.SaveChanges();
        }

        public async Task<int> DeleteAsync(TEntity entity)
        {
            db.Attach(entity);
            db.Remove(entity);
            return await db.SaveChangesAsync();
        }
        #endregion

        #region 添加
        public int AddEntity(TEntity entity)
        {
            db.Set<TEntity>().Add(entity);
            return db.SaveChanges();
        }

        public async Task<int> AddEntityAsync(TEntity entity)
        {
            db.Set<TEntity>().Add(entity);
            return await db.SaveChangesAsync();
        }

        public int AddList(IEnumerable<TEntity> entities)
        {
            //两种写法
            db.Set<TEntity>().AddRange(entities);
            //foreach (var item in entities)
            //{
            //    db.Set<TEntity>().Add(item);
            //}
            return db.SaveChanges();
        }

        public async Task<int> AddListAsync(IEnumerable<TEntity> entities)
        {
            db.Set<TEntity>().AddRange(entities);
            return await db.SaveChangesAsync();
        }
        #endregion
    }
}
